/*
 * This file is part of TradeHelper library.
 *
 * TradeHelper library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * TradeHelper library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with TradeHelper library.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.rag.forum.pages;

import com.alee.extended.breadcrumb.WebBreadcrumbToggleButton;
import com.alee.extended.layout.ToolbarLayout;
import com.alee.extended.layout.WebVerticalFlowLayout;
import com.alee.extended.panel.WebButtonGroup;
import com.alee.extended.panel.WebOverlay;
import com.alee.laf.StyleConstants;
import com.alee.laf.button.WebToggleButton;
import com.alee.laf.label.WebLabel;
import com.alee.laf.panel.WebPanel;
import com.alee.laf.progressbar.WebProgressBar;
import com.alee.laf.scroll.WebScrollPane;
import com.alee.managers.settings.SettingsManager;
import com.alee.utils.SwingUtils;
import com.rag.core.*;
import com.rag.managers.FavoritesManager;
import com.rag.managers.favorites.FavoritesListener;
import com.rag.utils.RagUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

/**
 * User: mgarin Date: 07.06.12 Time: 14:49
 */

public class FavoritePage extends WebPanel
{
    private static ImageIcon filtersIcon =
            new ImageIcon ( FavoritePage.class.getResource ( "icons/favorites/filters.png" ) );

    private static ImageIcon weaponIcon =
            new ImageIcon ( FavoritePage.class.getResource ( "icons/favorites/weapon.png" ) );
    private static ImageIcon armorIcon =
            new ImageIcon ( FavoritePage.class.getResource ( "icons/favorites/armor.png" ) );
    private static ImageIcon cardIcon =
            new ImageIcon ( FavoritePage.class.getResource ( "icons/favorites/card.png" ) );
    private static ImageIcon usableIcon =
            new ImageIcon ( FavoritePage.class.getResource ( "icons/favorites/usable.png" ) );
    private static ImageIcon otherIcon =
            new ImageIcon ( FavoritePage.class.getResource ( "icons/favorites/other.png" ) );

    private WebBreadcrumbToggleButton menuButton;

    private WebLabel progressLabel;
    private WebProgressBar progressBar;

    private WebPanel filtersPanel;
    private WebToggleButton filtersOn;
    private WebToggleButton sell;
    private WebToggleButton buy;
    private WebToggleButton weapon;
    private WebToggleButton armor;
    private WebToggleButton card;
    private WebToggleButton usable;
    private WebToggleButton other;

    private WebOverlay contentOverlay;
    private WebPanel contentPanel;
    private WebPanel progressPanel;

    public FavoritePage ( WebBreadcrumbToggleButton menuButton )
    {
        super ();

        this.menuButton = menuButton;

        String pageKey = "Favorites.";

        // Панель фильтров

        filtersPanel = new WebPanel ( true );
        filtersPanel.setMargin ( 4 );
        filtersPanel.setShadeWidth ( 0 );
        filtersPanel.setDrawSides ( false, false, true, false );
        filtersPanel.setLayout ( new ToolbarLayout ( 4, ToolbarLayout.HORIZONTAL ) );
        add ( filtersPanel, BorderLayout.NORTH );

        filtersOn = new WebToggleButton ( "Фильтры:", filtersIcon );
        SettingsManager.registerComponent ( filtersOn, pageKey + "filtersOn", true );
        filtersOn.setRound ( StyleConstants.smallRound );
        filtersOn.setDrawFocus ( false );
        filtersOn.setRolloverDecoratedOnly ( true );
        filtersPanel.add ( filtersOn );

        sell = new WebToggleButton ( "Продажа", TopicType.sell.getIcon () );
        SettingsManager.registerComponent ( sell, pageKey + "sellFilter", true );
        sell.setRound ( StyleConstants.smallRound );
        sell.setDrawFocus ( false );

        buy = new WebToggleButton ( "Покупка", TopicType.buy.getIcon () );
        SettingsManager.registerComponent ( buy, pageKey + "buyFilter", true );
        buy.setRound ( StyleConstants.smallRound );
        buy.setDrawFocus ( false );

        filtersPanel.add ( new WebButtonGroup ( sell, buy ) );

        weapon = new WebToggleButton ( "Оружие", weaponIcon );
        SettingsManager.registerComponent ( weapon, pageKey + "weaponFilter", true );
        weapon.setRound ( StyleConstants.smallRound );
        weapon.setDrawFocus ( false );

        armor = new WebToggleButton ( "Броня", armorIcon );
        SettingsManager.registerComponent ( armor, pageKey + "armorFilter", true );
        armor.setRound ( StyleConstants.smallRound );
        armor.setDrawFocus ( false );

        card = new WebToggleButton ( "Карточки", cardIcon );
        SettingsManager.registerComponent ( card, pageKey + "cardFilter", true );
        card.setRound ( StyleConstants.smallRound );
        card.setDrawFocus ( false );

        usable = new WebToggleButton ( "Расходка", usableIcon );
        SettingsManager.registerComponent ( usable, pageKey + "usableFilter", true );
        usable.setRound ( StyleConstants.smallRound );
        usable.setDrawFocus ( false );

        other = new WebToggleButton ( "Прочее", otherIcon );
        SettingsManager.registerComponent ( other, pageKey + "otherFilter", true );
        other.setRound ( StyleConstants.smallRound );
        other.setDrawFocus ( false );

        filtersPanel.add ( new WebButtonGroup ( weapon, armor, card, usable, other ) );

        // Слушатель обновления
        ActionListener updateListener = new ActionListener ()
        {
            public void actionPerformed ( ActionEvent e )
            {
                loadFavoriteTopics ();
            }
        };
        filtersOn.addActionListener ( updateListener );
        sell.addActionListener ( updateListener );
        buy.addActionListener ( updateListener );
        weapon.addActionListener ( updateListener );
        armor.addActionListener ( updateListener );
        card.addActionListener ( updateListener );
        usable.addActionListener ( updateListener );
        other.addActionListener ( updateListener );

        // Панель топиков
        contentPanel = new WebPanel ( new WebVerticalFlowLayout ( 0 ) );
        WebScrollPane scrollPane = new WebScrollPane ( contentPanel );
        scrollPane.setShadeWidth ( 5 );
        scrollPane.setDrawFocus ( false );
        contentOverlay = new WebOverlay ( scrollPane );
        contentOverlay.setMargin ( 5 );
        add ( contentOverlay, BorderLayout.CENTER );

        // Панель прогресса
        progressLabel = new WebLabel ( "", WebLabel.CENTER );
        progressBar = new WebProgressBar ( WebProgressBar.HORIZONTAL, 0, 100 );
        progressPanel = new WebPanel ( true );
        progressPanel.setMargin ( 10 );
        progressPanel.setShadeWidth ( 5 );
        progressPanel.setWebColored ( false );
        progressPanel.add ( progressLabel, BorderLayout.NORTH );
        progressPanel.add ( progressBar, BorderLayout.CENTER );
        contentOverlay.addOverlay ( progressPanel, SwingConstants.CENTER, SwingConstants.CENTER );

        // Загружаем список избранных топиков
        loadFavoriteTopics ();

        // Слушатель перетаскивания
        menuButton.setTransferHandler ( new TransferHandler ()
        {
            public boolean canImport ( TransferHandler.TransferSupport info )
            {
                return isDropEnabled ();
            }

            public boolean importData ( TransferHandler.TransferSupport info )
            {
                return info.isDrop () && importData ( info.getTransferable () );
            }

            public boolean importData ( Transferable t )
            {
                return isDropEnabled () && itemsImported ( t );
            }

            protected boolean isDropEnabled ()
            {
                return FavoritePage.this.isEnabled ();
            }

            protected boolean itemsImported ( Transferable t )
            {
                return FavoritesManager.addFavoriteTopic ( RagUtils.getTopicData ( t ) );
            }
        } );

        // Слушатель изменений избранного
        FavoritesManager.addFavoritesListener ( new FavoritesListener ()
        {
            public void favoriteTopicAdded ( SingleTopicData added )
            {
                addFavoriteTopic ( added );
            }

            public void favoriteTopicsUpdated ( List<SingleTopicData> updated )
            {
                updateFavoriteTopics ( updated );
            }

            public void favoriteTopicRemoved ( SingleTopicData removed )
            {
                removeFavoriteTopic ( removed );
            }
        } );
    }

    private void addFavoriteTopic ( SingleTopicData added )
    {
        loadFavoriteTopics ();
    }

    private void updateFavoriteTopics ( List<SingleTopicData> updated )
    {
        loadFavoriteTopics ();
    }

    private void removeFavoriteTopic ( SingleTopicData removed )
    {
        loadFavoriteTopics ();
    }

    private void loadFavoriteTopics ()
    {
        // Добавляем панель прогресса          
        startProgress ();

        // Создаём отображение топиков в отдельном потоке
        new Thread ( new Runnable ()
        {
            public void run ()
            {
                // Получаем список отфильтрованных топиков
                final List<SingleTopicData> favorites = getFilteredTopics ();

                // Создаём панели с содержимым
                int i = 1;
                final List<WebPanel> panels = new ArrayList<WebPanel> ();
                for ( SingleTopicData topicData : favorites )
                {
                    // Обновляем состояние прогресса
                    final int fi = i;
                    SwingUtils.invokeAndWaitSafely ( new Runnable ()
                    {
                        public void run ()
                        {
                            progressLabel.setText ( "Загрузка избранных топиков: " + fi + " из " +
                                    favorites.size () );
                            progressBar.setValue ( 100 * fi / favorites.size () );
                            menuButton.setProgress ( ( float ) fi / favorites.size () );
                        }
                    } );

                    // Создаём или получаем ранее созданную панель топика
                    panels.add (
                            new TopicContentPanel ( ForumType.favorites, topicData, favorites, true,
                                    true, false, false ) );

                    i++;
                }
                SwingUtils.invokeAndWaitSafely ( new Runnable ()
                {
                    public void run ()
                    {
                        progressLabel.setText ( "Загрузка отображения..." );
                        progressBar.setValue ( 100 );
                        menuButton.setProgress ( 1f );
                    }
                } );

                // Обновляем отображение
                SwingUtils.invokeLater ( new Runnable ()
                {
                    public void run ()
                    {
                        // Прячем прогресс
                        endProgress ();

                        // Добавляем созданные панели
                        contentPanel.removeAll ();
                        contentPanel.add ( panels );
                        contentPanel.revalidate ();
                        contentPanel.repaint ();
                    }
                } );
            }
        } ).start ();
    }

    private void startProgress ()
    {
        menuButton.setShowProgress ( true );
        progressPanel.setVisible ( true );
        SwingUtils.setEnabledRecursively ( filtersPanel, false );
    }

    private void endProgress ()
    {
        menuButton.setShowProgress ( false );
        progressPanel.setVisible ( false );
        SwingUtils.setEnabledRecursively ( filtersPanel, true );
    }

    private List<SingleTopicData> getFilteredTopics ()
    {
        final List<SingleTopicData> topics = new ArrayList<SingleTopicData> ();
        for ( SingleTopicData topic : FavoritesManager.getFavorites () )
        {
            SingleTopicData filtered = getFilteredTopic ( topic );
            if ( filtered != null )
            {
                topics.add ( filtered );
            }
        }
        return topics;
    }

    private SingleTopicData getFilteredTopic ( SingleTopicData topic )
    {
        SingleTopicData accepted;
        // Проверяем подходит ли топик по фильтрам
        if ( acceptedByFilters ( topic ) )
        {
            // Клонируем даные по каждому топику и удаляем не проходящие фильтр
            SingleTopicData filtered = topic.clone ();
            List<ItemData> parsedItems = filtered.getParsedItems ();
            for ( int i = parsedItems.size () - 1; i >= 0; i-- )
            {
                ItemData itemData = parsedItems.get ( i );
                if ( !acceptedByFilters ( itemData.getItem () ) )
                {
                    boolean contains = false;
                    if ( itemData.getCardIds () != null )
                    {
                        for ( Item card : itemData.getCards () )
                        {
                            if ( acceptedByFilters ( card ) )
                            {
                                contains = true;
                                break;
                            }
                        }
                    }
                    if ( !contains )
                    {
                        parsedItems.remove ( i );
                    }
                }
            }
            accepted = parsedItems.size () > 0 ? filtered : null;
        }
        else
        {
            accepted = null;
        }
        return accepted;
    }

    private boolean acceptedByFilters ( SingleTopicData topic )
    {
        return !filtersOn.isSelected () || ( sell.isSelected () &&
                ( topic.getTopicType ().equals ( TopicType.sell ) ||
                        topic.getTopicType ().equals ( TopicType.pricecheck ) ) ||
                buy.isSelected () && topic.getTopicType ().equals ( TopicType.buy ) );
    }

    private boolean acceptedByFilters ( Item item )
    {
        return !filtersOn.isSelected () || ( weapon.isSelected () && isWeapon ( item ) ||
                armor.isSelected () && isArmor ( item ) ||
                card.isSelected () && isCard ( item ) ||
                usable.isSelected () && isUsable ( item ) ||
                other.isSelected () && isOther ( item ) );
    }

    private boolean isWeapon ( Item item )
    {
        return item.getItemType ().equals ( ItemType.weapon ) ||
                item.getItemType ().equals ( ItemType.throwWeapon );
    }

    private boolean isArmor ( Item item )
    {
        return item.getItemType ().equals ( ItemType.armor ) ||
                item.getItemType ().equals ( ItemType.petArmor );
    }

    private boolean isCard ( Item item )
    {
        return item.getItemType ().equals ( ItemType.card );
    }

    private boolean isUsable ( Item item )
    {
        return item.getItemType ().equals ( ItemType.healingItem ) ||
                item.getItemType ().equals ( ItemType.usableItem ) ||
                item.getItemType ().equals ( ItemType.ammunition ) ||
                item.getItemType ().equals ( ItemType.delayedConsumable );
    }

    private boolean isOther ( Item item )
    {
        return item.getItemType ().equals ( ItemType.miscellaneous ) ||
                item.getItemType ().equals ( ItemType.monsterEgg ) ||
                item.getItemType ().equals ( ItemType.tamingItem ) ||
                item.getItemType ().equals ( ItemType.cashShopItem );
    }
}